package net.csdn.business.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.vladsch.flexmark.ext.yaml.front.matter.AbstractYamlFrontMatterVisitor;
import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.DataKey;
import com.vladsch.flexmark.util.data.MutableDataSet;
import net.csdn.business.common.constant.AuditConstants;
import net.csdn.business.common.constant.CommonConstants;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author likun
 * @date 2022/6/6 18:37
 */
public class BusinessUtil {
    private static final String SEPARATOR = ",";
    private final static String NO_FILE_EOL_OPTION_NAME = "NO_FILE_EOL";
    private final static DataKey<Boolean> NO_FILE_EOL = new DataKey<>(NO_FILE_EOL_OPTION_NAME, true);
    private final static DataHolder MD_OPTIONS = new MutableDataSet()
            .set(NO_FILE_EOL, false)
            .set(Parser.EXTENSIONS, Collections.singleton(YamlFrontMatterExtension.create()))
            .toImmutable();
    private final static Parser MD_PARSER = Parser.builder(MD_OPTIONS).build();

    public static String genTraceId() {
        return RandomUtil.randomString(12);
    }

    public static String getChildIds(String ids, String id, int replyChildMaxCount) {
        if (ObjectUtils.isEmpty(ids)) {
            return id;
        }
        List<String> childIds = Lists.newArrayList(StringUtils.split(ids, SEPARATOR));
        if (CollectionUtils.isEmpty(childIds)) {
            return id;
        }
        if (childIds.size() < replyChildMaxCount) {
            childIds.add(id);
        }
        return StringUtils.join(childIds, SEPARATOR);
    }

    public static List<String> splitStr(String s, String separator) {
        if (StringUtils.isBlank(s)) {
            return Lists.newArrayList();
        }
        String[] ids = StringUtils.split(s, separator);
        if (null == ids) {
            return Lists.newArrayList();
        }
        return Lists.newArrayList(ids);
    }

    public static List<String> splitStr(String s) {
        return splitStr(s, SEPARATOR);
    }

    public static String formatAvatarAddress(String address, String defaultAddress) {
        if (StringUtils.isBlank(address)) {
            return defaultAddress;
        }
        int index = address.indexOf("uploads/user/");
        return index < CommonConstants.INT_ZERO ? defaultAddress : ("/" + address.substring(index));
    }

    public static String formatAvatarAddress(String address, String defaultAddress, String prefix) {
        return prefix + formatAvatarAddress(address, defaultAddress);
    }

    public static String formatOrgLogo(String logo, String prefix) {
        if (StringUtils.isBlank(logo)) {
            return logo;
        }
        return prefix + logo;
    }

    public static String substring(String s, int len, String suffix) {
        if (StringUtils.isBlank(s) || s.length() <= len) {
            return s;
        }
        return StringUtils.substring(s, CommonConstants.INT_ZERO, len - suffix.length()) + suffix;
    }

    public static String substring(String s, int len) {
        return substring(s, len, "...");
    }

    public static String notifyContentSubstring(String s) {
        return substring(s, CommonConstants.NOTIFY_CONTENT_SIZE);
    }

    public static String formatAuditMqType(String type) {
        String instanceName = type;
        if (StringUtils.indexOf(type, AuditConstants.VERTICAL_LINE) >= CommonConstants.INT_ZERO) {
            instanceName = StringUtils.split(type, AuditConstants.VERTICAL_LINE)[1];
        }
        return instanceName;
    }

    public static <T> List<T> listUnion(List<T> a, List<T> b) {
        return Lists.newArrayList(CollectionUtil.unionDistinct(a, b));
    }

    public static <T> List<T> listSubtract(List<T> a, List<T> b) {
        if (CollectionUtil.isEmpty(a)) {
            return CollectionUtil.isEmpty(b) ? Lists.newArrayList() : b;
        }
        return ((List<T>) CollectionUtil.subtract(a, b));
    }

    public static <T> T mergeBean(T sourceBean, T targetBean) {
        Class<?> sourceBeanClass = sourceBean.getClass();
        Class<?> targetBeanClass = targetBean.getClass();

        Field[] sourceFields = sourceBeanClass.getDeclaredFields();
        Field[] targetFields = targetBeanClass.getDeclaredFields();
        for (int i = 0, l = sourceFields.length; i < l; i++) {
            Field sourceField = sourceFields[i];
            Field targetField = targetFields[i];
            sourceField.setAccessible(true);
            targetField.setAccessible(true);
            try {
                if (null != sourceField.get(sourceBean)) {
                    targetField.set(targetBean, sourceField.get(sourceBean));
                }
            } catch (IllegalArgumentException | IllegalAccessException ignore) {

            }
        }
        return targetBean;
    }

    public static String getFileName(String path) {
        if (StringUtils.isBlank(path)) {
            return "";
        }
        String[] paths = StringUtils.split(path, "/");
        return paths[paths.length - 1];
    }

    public static Map<String, List<String>> parseMdFrontMatter(String md) {
        // final String input = "---\n" +
        //         "name: Bug Report\n" +
        //         "about: Report a bug in Dubbo\n" +
        //         "title: ''\n" +
        //         "labels: type/bug\n" +
        //         "assignees: ''\n" +
        //         "\n" +
        //         "---";

        AbstractYamlFrontMatterVisitor visitor = new AbstractYamlFrontMatterVisitor();
        Node document = MD_PARSER.parse(md);
        visitor.visit(document);

        Map<String, List<String>> data = visitor.getData();
        return CollectionUtils.isEmpty(data) ? Maps.newHashMap() : data;
    }

    public static String removeMdFrontMatter(String md) {
        // return ReUtil.replaceAll(md, "(---(\\S|\\s)*---)", "");
        return ReUtil.replaceAll(md, "---(.*)?---", "");
    }

    public static String removePrefixAndSuffix(String s, String symbol) {
        if (StrUtil.isEmpty(s) || StrUtil.isEmpty(symbol)) {
            return StrUtil.str(s);
        }
        s = StrUtil.removePrefix(s, symbol);
        return StrUtil.removeSuffix(s, symbol);
    }

    public static String mdToHtml(String md) {
        MutableDataSet options = new MutableDataSet();
        Parser parser = Parser.builder(options).build();
        HtmlRenderer renderer = HtmlRenderer.builder(options).build();
        Node document = parser.parse(md);
        return renderer.render(document);
    }
}